package auto.app.service.impl;

import auto.app.controller.from.menus.MenusAddFrom;
import auto.app.controller.from.menus.MenusUpdateFrom;
import auto.app.controller.from.menus.updateRuleMenusFrom;
import auto.app.controller.info.MenusInfo;
import auto.app.exetion.MainExection;
import auto.app.model.Menus;
import auto.app.dao.MenusDao;
import auto.app.model.RuleMenus;
import auto.app.service.MenusService;
import auto.app.service.RuleMenusService;
import auto.app.util.CommonUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.dc.pr.PRError;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static auto.app.exetion.MainExetionMessage.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 杨森
 * @since 2022-07-08
 */
@Service
public class MenusServiceImpl extends ServiceImpl<MenusDao, Menus> implements MenusService {

    @Autowired
    private MenusDao menusDao;

    @Autowired
    private RuleMenusService ruleMenusService;

    @Override
    public List<MenusInfo> slectWoniuMenus(Integer id) throws MainExection {
        List<Menus> menus = menusDao.findMenus(id);
        if (menus == null || menus.size() == 0)
            throw new MainExection(MENUSSELECTNULL.getCode(), MENUSSELECTNULL.getMsg());
        //将查询出来的菜单负值到视图类中
        List<MenusInfo> menusInfos = CommonUtil.copyList(menus, MenusInfo.class);
        //进行数据处理
        HashMap<Integer, MenusInfo> MenusInfoHashMap = new HashMap<>();
        //首先将所以的菜单放入map集合中
        for (MenusInfo menusInfo : menusInfos) {
            MenusInfoHashMap.put(menusInfo.getMenusId(), menusInfo);
        }
        //对集合中的菜单便利并且放入父节点下（仅支持2级）
        for (MenusInfo menusInfo : menusInfos) {
            //根据父节点id获取对象
            MenusInfo menusInfoParent = MenusInfoHashMap.get(menusInfo.getMenusParentid());
            //若存在父节点走下面逻辑
            if (menusInfoParent != null) {
                //判断父节点类中的MenusInfoList是否为null 为空添加arraylist数组
                if (menusInfoParent.getMenusInfoList() == null)
                    menusInfoParent.setMenusInfoList(new ArrayList<MenusInfo>());
                //若不为空直接添加子节点数据
                menusInfoParent.getMenusInfoList().add(menusInfo);
                //从map集合中移除子节点数据
                MenusInfoHashMap.remove(menusInfo.getMenusId());
            }
        }
        //对map集合中的数据进行便利 并存入数组
        //创建arraylist数组
        ArrayList<MenusInfo> arrayList = new ArrayList<>();
        Iterator<Map.Entry<Integer, MenusInfo>> iterator = MenusInfoHashMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, MenusInfo> next = iterator.next();
            arrayList.add(next.getValue());
        }
        return arrayList;
    }

    /**
     * 新增菜单
     * @param menusAddFrom
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addMenus(MenusAddFrom menusAddFrom) throws MainExection {
        //判断菜单名称是否存在
        Menus one = this.getOne(new LambdaQueryWrapper<Menus>().eq(Menus::getMenusName, menusAddFrom.getMenusName()));
        if (ObjectUtil.isNotNull(one)){
            throw new MainExection(MENUSNAMEEMPTY.getCode(),MENUSNAMEEMPTY.getMsg());
        }
        if (menusAddFrom.getMenusParentid()!=0){
            //判断父级ID 且父级不是叶子节点
            Menus menus = this.getOne(new LambdaQueryWrapper<Menus>().eq(Menus::getMenusParentid, menusAddFrom.getMenusParentid()).eq(Menus::getMenusType, 0));
            if (ObjectUtil.isNotNull(menus)){
                throw new MainExection(MENUSPARMENTEMPTY.getCode(),MENUSPARMENTEMPTY.getMsg());
            }
        }
        Menus menus = CommonUtil.copyOne(menusAddFrom, Menus.class);
        menus.setCreateTime(LocalDateTime.now());
        return this.save(menus);
    }

    /**
     * 修改菜单
     * @param menusUpdateFrom
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateMenus(MenusUpdateFrom menusUpdateFrom) throws MainExection {
        Menus menus = this.getOne(new LambdaQueryWrapper<Menus>().eq(Menus::getMenusName, menusUpdateFrom.getMenusName())
        .ne(Menus::getMenusId,menusUpdateFrom.getMenusId()));
        if (ObjectUtil.isNotNull(menus)){
            throw new MainExection(MENUSNAMEEMPTY.getCode(),MENUSNAMEEMPTY.getMsg());
        }
        if (menusUpdateFrom.getMenusParentid()!=0){
            //判断父级ID 且父级不是叶子节点
            Menus menusParent = this.getOne(new LambdaQueryWrapper<Menus>().eq(Menus::getMenusParentid, menusUpdateFrom.getMenusParentid()).eq(Menus::getMenusType, 0));
            if (ObjectUtil.isNotNull(menusParent)){
                throw new MainExection(MENUSPARMENTEMPTY.getCode(),MENUSPARMENTEMPTY.getMsg());
            }
        }
        Menus copyOne = CommonUtil.copyOne(menusUpdateFrom, Menus.class);
        copyOne.setUpdateTime(LocalDateTime.now());
        return this.updateById(copyOne);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateRuleMenus(updateRuleMenusFrom updateRuleMenusFrom) {
        //查询出对应角色之前的所有数据
        List<RuleMenus> list = ruleMenusService.list(new LambdaQueryWrapper<RuleMenus>().eq(RuleMenus::getRuleId, updateRuleMenusFrom.getRuleId()));
        List<Integer> collect = list.stream().map(RuleMenus::getRuleMenusId).collect(Collectors.toList());
        ruleMenusService.removeByIds(collect);
        ArrayList<RuleMenus>arrayList=new ArrayList<>();
        List<Integer> menusIdlist = updateRuleMenusFrom.getMenusIdlist();
        for (Integer integer : menusIdlist) {
            RuleMenus ruleMenus=new RuleMenus();
            ruleMenus.setMenusId(integer);
            ruleMenus.setRuleId(updateRuleMenusFrom.getRuleId());
            arrayList.add(ruleMenus);
        }
        return ruleMenusService.saveBatch(arrayList);
    }
}
